// 
// Created By: Xiaofeng.Gu 2021/03/23
// 
// Description: NodeSONClient

#pragma once

#include "cybertron/network/SocketTcpClientSync.hpp"
#include "cybertron/core/ConcurrentQueue.hpp"
#include "Node/TaskRunnerPool.pb.h"
#include <chrono>
#include <atomic>
#include <thread>

CYBERTRON_BEGIN


struct TaskNodeInfo {
	string nodeId;
	Common::EWorkNodeType workType;
	string groupId;
	string description;
	string userData;
	string tag;
};

class TaskRunnerPoolClient : public std::enable_shared_from_this<TaskRunnerPoolClient>
{
public:
	CybertronCoreAPI TaskRunnerPoolClient();
	CybertronCoreAPI virtual~TaskRunnerPoolClient();

	CybertronCoreAPI bool isEnable();
	CybertronCoreAPI void enable(bool enable);

	CybertronCoreAPI bool initialize(std::string groupId, Common::EWorkNodeType workType, std::string id,
		std::string description = "", std::string userData = "", std::string tag = "");

	CybertronCoreAPI bool setServerInfo(const std::string& serverAddr, int port);
	
	CybertronCoreAPI void updateTaskStateToServer(TaskRunnerPool::ETaskRunnerPoolState state);
	
	CybertronCoreAPI TaskRunnerPool::ETaskRunnerPoolState getState();

protected:
	void onServerMessage(const cybertron::Message& msg);
	// handle messages
	void onHandleHeartbeatMessage(const cybertron::Message& msg);
	void onHandleRegisterRequestMessage(const cybertron::Message& msg);
	void onHandleNodeStateReqMessage(const cybertron::Message& msg);
	void onHandleNodeStateRetMessage(const cybertron::Message& msg);

	void commitRegisterCommand();
	void commitReportState();
	void sendHeartbeat();
protected:
	string GetKey(string groupId, string id, string type);
	void run();
	ESocketStatus getSocketStatus();
	void closeSocket();
	void pushCommand(const std::string& command);
	int runCommands(bool hasHeartbeat);

private:
	void zeroMembers();

private:

	ConcurrentQueue<std::string> mCommandQueue;

	cybertron::SocketTcpClientSync mTcpClient;

	std::string mTaskRunnerPoolServerIp = "127.0.0.1";
	int mTaskRunnerPoolServerPort = 23790;

	TaskNodeInfo mNodeInfo;
	TaskRunnerPool::ETaskRunnerPoolState mState;

	std::thread mRunningThread;

	bool mbEnable;
};


CYBERTRON_END
